package main

import (
	"bufio"
	"config-client-v1/test/fs-server/pkg"
	"config-client-v1/utils/tools"
	"flag"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/olekukonko/tablewriter"
	"log"
	"net"
	"os"
	"runtime/debug"
	"strconv"
	"strings"
	"time"
)

const ByteLENGTH = 4096 // 单次循环最大读取的字节数量, 如果单次发送的数据包大于这里, 则需要多次读取

var userNum int

var OnlineMap pkg.OnlineMapStu
var serverPort string
var fse *pkg.FSEquip

func init() {
	port := flag.String("port", "8123", "tcp server port")
	httpPort := flag.String("http_port", "8223", "http server port")
	fseID := flag.String("fse", "1", "自研设备ID")
	flag.Parse()
	serverPort = *port
	HttpPort = *httpPort
	OnlineMap = pkg.OnlineMapStu{}
	OnlineMap.M = make(map[string]*pkg.Client)
	OnlineMap.Register = make(chan *pkg.Client, 1000)
	OnlineMap.Unregister = make(chan *pkg.Client, 1000)
	fse = pkg.LoadingFSE(*fseID)
}

func main() {
	go connManage()
	listener, err := net.Listen("tcp", ":"+serverPort)
	if err != nil {
		log.Fatal("tcp 服务启动失败 " + err.Error())
	}
	fmt.Printf("%-32s%-32s\n", "tcp listen on "+serverPort, "OK")
	go HttpRun()
	for {
		conn, err2 := listener.Accept()
		if err2 != nil {
			fmt.Println("listener Accept Error", err2)
			break
		}
		remoteAddr := conn.RemoteAddr().String()
		reader := bufio.NewReader(conn)
		client := &pkg.Client{
			RemoteAddr:   remoteAddr,
			Connection:   conn,
			Reader:       reader,
			CreateTime:   time.Now(),
			LastDataTime: time.Now(),
		}
		OnlineMap.Register <- client
		userNum++
		//conn.Write([]byte("ping"))
		//_ = conn.SetReadDeadline(time.Now().Add(10 * time.Second))
		go handleCon(client)
	}
}

func handleCon(client *pkg.Client) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("handleCon Error: ", err)
			debug.PrintStack()
		}
		OnlineMap.Unregister <- client
	}()
	remoteAddr := client.Connection.RemoteAddr().String() // 客户端IP:PORT
	var buffer [ByteLENGTH]byte
	code1 := fse.Code1
loop0:
	for {
		n, err := client.Connection.Read(buffer[0:])
		if err != nil {
			if err == net.ErrClosed || strings.Contains(err.Error(), "use of closed network connection") || strings.Contains(err.Error(), "read: connection reset by peer") || strings.Contains(err.Error(), "forcibly closed") {
				fmt.Printf("[%s ~ %s]# 连接已关闭或重置\n", tools.GetNow(), remoteAddr)
			} else {
				fmt.Println("unknown read error: ", err.Error())
			}
			return
		}

		OnlineMap.Register <- client
		str := tools.ByteArrayToHexStr(buffer[0:n])
		fmt.Printf("[%s ~ %s]# len=%d : %s\n", tools.GetNow(), remoteAddr, n, str)
		//_ = tools.WriteStringToLog(fmt.Sprintf("[%s ~ %s]# %s", tools.GetNow(), remoteAddr, str), "well_raw_data.log", "")
		/* --- 处理 rawData 开始 --- */
		//now := tools.GetNow()
		fmt.Println("-----------------------------")
		//funcCode := buffer[1]
		if n < 6 {
			fmt.Printf("[%s ~ %s]# 数据帧长度小于6\n", tools.GetNow(), remoteAddr)
			continue
		}
		if buffer[0] != 0x5a || buffer[n-1] != 0xa5 {
			fmt.Printf("[%s ~ %s]# 无效的帧头帧尾\n", tools.GetNow(), remoteAddr)
			continue
		}

		funcCode := buffer[1]
		cmdCode := buffer[2]
		length := tools.BytesToUint16(buffer[3:5], "big")
		if int(length) != n {
			fmt.Printf("[%s ~ %s]# 数据帧长度与实际不匹配 n=%d; length=%d\n", tools.GetNow(), remoteAddr, n, length)
		}
		data := make([][]string, 0)
		switch funcCode {
		case 0x01:
			switch cmdCode {
			case 0x01:
				if time.Now().Unix()%2 == 1 {
					// 正常返回
					resp, err := pkg.GenFSFrameData0102(fse.IP, fse.RedundantIP, uint16(fse.Port), uint16(fse.RedundantPort), fse.RedundantParam1, fse.RedundantParam2, fse.RedundantParam3, fse.RedundantEnable)
					if err != nil {
						fmt.Println("GenFSFrameData0102 Error: ", err)
						continue loop0
					}
					resp[2] = 0x01
					_, _ = client.Connection.Write(resp)
				} else {
					// 错误返回
					_, err = client.Connection.Write([]byte{0x5a, 0x01, 0x81, 0x00, 0x0C, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa5})
				}
			case 0x02:
				// 收到IP设置命令
				fmt.Printf("[%s ~ %s]# 收到IP设置指令 %02d%02d\n", tools.GetNow(), remoteAddr, funcCode, cmdCode)

				if time.Now().Unix()%2 == 1 {
					_, err = client.Connection.Write(buffer[0:n])
				} else {
					_, err = client.Connection.Write([]byte{0x5a, 0x01, 0x82, 0x00, 0x0C, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa5})
				}
			default:
				fmt.Printf("[%s ~ %s]# 暂不支持的指令码\n", tools.GetNow(), remoteAddr)
			}
		case 0x02:
			switch cmdCode {
			case 0x02:
				/*--- 更新数据规模 start ---*/
				m := &pkg.FSModule{}
				m.Code1 = code1
				m.Code2 = "00"
				m.Code3 = fmt.Sprintf("%02d", buffer[8])
				frameItem := make([]*pkg.FrameItem, 0)
				/*--- 更新数据规模 end ---*/

				fmt.Printf("[%s ~ %s]# AI模块下载\n", tools.GetNow(), remoteAddr)
				AINum := buffer[7]
				AICode := buffer[8]
				ChannelNum := buffer[9]
				fmt.Printf("[%s ~ %s]# AI总数=%d, AI序号=%02d, AI通道数=%d\n", tools.GetNow(), remoteAddr, AINum, AICode, ChannelNum)
				contentBytes := buffer[10 : n-5]
				blockLength := 28
				if len(contentBytes) != int(ChannelNum)*blockLength {
					fmt.Printf("[%s ~ %s]# AI通道数与实际不匹配\n", tools.GetNow(), remoteAddr)
					continue
				}
				for i := 0; i < int(ChannelNum); i++ {
					upperLimitValue := tools.BytesToFloat32(contentBytes[i*blockLength:i*blockLength+4], "little")
					lowerLimitValue := tools.BytesToFloat32(contentBytes[i*blockLength+4:i*blockLength+8], "little")
					upper2LimitValue := tools.BytesToFloat32(contentBytes[i*blockLength+8:i*blockLength+12], "little")
					lower2LimitValue := tools.BytesToFloat32(contentBytes[i*blockLength+12:i*blockLength+16], "little")
					rangeUpperValue := tools.BytesToFloat32(contentBytes[i*blockLength+16:i*blockLength+20], "little")
					rangeLowerValue := tools.BytesToFloat32(contentBytes[i*blockLength+20:i*blockLength+24], "little")
					shield := contentBytes[i*blockLength+24]
					alertBit := contentBytes[i*blockLength+25]
					formula := contentBytes[i*blockLength+26]
					diagMode := contentBytes[i*blockLength+27]
					data = append(data, []string{
						fmt.Sprintf("%02d", i),
						fmt.Sprintf("%.2f", upperLimitValue),
						fmt.Sprintf("%.2f", lowerLimitValue),
						fmt.Sprintf("%.2f", upper2LimitValue),
						fmt.Sprintf("%.2f", lower2LimitValue),
						fmt.Sprintf("%.2f", rangeUpperValue),
						fmt.Sprintf("%.2f", rangeLowerValue),
						fmt.Sprintf("%d", shield),
						fmt.Sprintf("%d", alertBit),
						fmt.Sprintf("%d", formula),
						fmt.Sprintf("%d", diagMode),
					})

					/*--- 更新数据规模 start ---*/
					frameItem = append(frameItem, &pkg.FrameItem{
						Code4:            fmt.Sprintf("%03d", i),
						Addr:             fmt.Sprintf("%s-%s-%s-%03d", m.Code1, m.Code2, m.Code3, i),
						UpperLimitValue:  float64(upperLimitValue),
						LowerLimitValue:  float64(lowerLimitValue),
						Upper2LimitValue: float64(upper2LimitValue),
						Lower2LimitValue: float64(lower2LimitValue),
						RangeUpperLimit:  float64(rangeUpperValue),
						RangeLowerLimit:  float64(rangeLowerValue),
						Shield:           shield,
						AlertBit:         alertBit,
						Formula:          formula,
						DiagMode:         diagMode,
						ChannelType:      "AI",
					})
					/*--- 更新数据规模 end ---*/
				}

				/*--- 更新数据规模 start ---*/
				m.FrameItem = frameItem
				pkg.UpdateFSE(fse, m)
				/*--- 更新数据规模 end ---*/

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"通道号", "上限", "下限", "上上限", "下下限", "量程上限", "量程下限", "屏蔽", "报警", "计算公式", "诊断模式"})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()

				_, err = client.Connection.Write([]byte{0x5a, 0x02, 0x02, 0x00, 0x0F, 0x01, 0x01, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0202")
					continue
				}
			case 0x03:
				/*--- 更新数据规模 start ---*/
				m := &pkg.FSModule{}
				m.Code1 = code1
				m.Code2 = "01"
				m.Code3 = fmt.Sprintf("%02d", buffer[8])
				frameItem := make([]*pkg.FrameItem, 0)
				/*--- 更新数据规模 end ---*/

				fmt.Printf("[%s ~ %s]# AQ模块下载\n", tools.GetNow(), remoteAddr)
				AINum := buffer[7]
				AICode := buffer[8]
				ChannelNum := buffer[9]
				fmt.Printf("[%s ~ %s]# AQ总数=%d, AQ序号=%02d, AQ通道数=%d\n", tools.GetNow(), remoteAddr, AINum, AICode, ChannelNum)
				contentBytes := buffer[10 : n-5]
				blockLength := 28
				if len(contentBytes) != int(ChannelNum)*blockLength {
					fmt.Printf("[%s ~ %s]# AQ通道数与实际不匹配\n", tools.GetNow(), remoteAddr)
					continue
				}
				for i := 0; i < int(ChannelNum); i++ {
					upperLimitValue := tools.BytesToFloat32(contentBytes[i*blockLength:i*blockLength+4], "little")
					lowerLimitValue := tools.BytesToFloat32(contentBytes[i*blockLength+4:i*blockLength+8], "little")
					upper2LimitValue := tools.BytesToFloat32(contentBytes[i*blockLength+8:i*blockLength+12], "little")
					lower2LimitValue := tools.BytesToFloat32(contentBytes[i*blockLength+12:i*blockLength+16], "little")
					rangeUpperValue := tools.BytesToFloat32(contentBytes[i*blockLength+16:i*blockLength+20], "little")
					rangeLowerValue := tools.BytesToFloat32(contentBytes[i*blockLength+20:i*blockLength+24], "little")
					shield := contentBytes[i*blockLength+24]
					alertBit := contentBytes[i*blockLength+25]
					formula := contentBytes[i*blockLength+26]
					diagMode := contentBytes[i*blockLength+27]
					data = append(data, []string{
						fmt.Sprintf("%02d", i),
						fmt.Sprintf("%.2f", upperLimitValue),
						fmt.Sprintf("%.2f", lowerLimitValue),
						fmt.Sprintf("%.2f", upper2LimitValue),
						fmt.Sprintf("%.2f", lower2LimitValue),
						fmt.Sprintf("%.2f", rangeUpperValue),
						fmt.Sprintf("%.2f", rangeLowerValue),
						fmt.Sprintf("%d", shield),
						fmt.Sprintf("%d", alertBit),
						fmt.Sprintf("%d", formula),
						fmt.Sprintf("%d", diagMode),
					})

					/*--- 更新数据规模 start ---*/
					frameItem = append(frameItem, &pkg.FrameItem{
						Code4:            fmt.Sprintf("%03d", i),
						Addr:             fmt.Sprintf("%s-%s-%s-%03d", m.Code1, m.Code2, m.Code3, i),
						UpperLimitValue:  float64(upperLimitValue),
						LowerLimitValue:  float64(lowerLimitValue),
						Upper2LimitValue: float64(upper2LimitValue),
						Lower2LimitValue: float64(lower2LimitValue),
						RangeUpperLimit:  float64(rangeUpperValue),
						RangeLowerLimit:  float64(rangeLowerValue),
						Shield:           shield,
						AlertBit:         alertBit,
						Formula:          formula,
						DiagMode:         diagMode,
						ChannelType:      "AQ",
					})
					/*--- 更新数据规模 end ---*/
				}

				/*--- 更新数据规模 start ---*/
				m.FrameItem = frameItem
				pkg.UpdateFSE(fse, m)
				/*--- 更新数据规模 end ---*/

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"通道号", "上限", "下限", "上上限", "下下限", "量程上限", "量程下限", "屏蔽", "报警", "计算公式", "诊断模式"})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()

				_, err = client.Connection.Write([]byte{0x5a, 0x02, 0x03, 0x00, 0x0F, 0x01, 0x01, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0203")
					continue
				}
			case 0x04:
				/*--- 更新数据规模 start ---*/
				m := &pkg.FSModule{}
				m.Code1 = code1
				m.Code2 = "02"
				m.Code3 = fmt.Sprintf("%02d", buffer[8])
				frameItem := make([]*pkg.FrameItem, 0)
				/*--- 更新数据规模 end ---*/

				fmt.Printf("[%s ~ %s]# DI模块下载\n", tools.GetNow(), remoteAddr)
				AINum := buffer[7]
				AICode := buffer[8]
				ChannelNum := buffer[9]
				fmt.Printf("[%s ~ %s]# DI总数=%d, DI序号=%02d, DI通道数=%d\n", tools.GetNow(), remoteAddr, AINum, AICode, ChannelNum)
				contentBytes := buffer[10 : n-5]
				blockLength := 3
				if len(contentBytes) != int(ChannelNum)*blockLength {
					fmt.Printf("[%s ~ %s]# DI通道数与实际不匹配\n", tools.GetNow(), remoteAddr)
					continue
				}
				for i := 0; i < int(ChannelNum); i++ {
					shield := contentBytes[i*blockLength]
					shieldTime := tools.BytesToUint16(contentBytes[i*blockLength+1:i*blockLength+3], "big")
					data = append(data, []string{
						fmt.Sprintf("%02d", i),
						fmt.Sprintf("%d", shield),
						fmt.Sprintf("%d", shieldTime),
					})

					/*--- 更新数据规模 start ---*/
					frameItem = append(frameItem, &pkg.FrameItem{
						Code4:       fmt.Sprintf("%03d", i),
						Addr:        fmt.Sprintf("%s-%s-%s-%03d", m.Code1, m.Code2, m.Code3, i),
						Shield:      shield,
						ShieldTime:  int(shieldTime),
						ChannelType: "DI",
					})
					/*--- 更新数据规模 end ---*/
				}
				/*--- 更新数据规模 start ---*/
				m.FrameItem = frameItem
				pkg.UpdateFSE(fse, m)
				/*--- 更新数据规模 end ---*/

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"通道号", "滤波选择", "滤波时间"})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()

				_, err = client.Connection.Write([]byte{0x5a, 0x02, 0x04, 0x00, 0x0F, 0x01, 0x01, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0204")
					continue
				}
			case 0x05:
				/*--- 更新数据规模 start ---*/
				m := &pkg.FSModule{}
				m.Code1 = code1
				m.Code2 = "03"
				m.Code3 = fmt.Sprintf("%02d", buffer[8])
				frameItem := make([]*pkg.FrameItem, 0)
				/*--- 更新数据规模 end ---*/

				fmt.Printf("[%s ~ %s]# DQ模块下载\n", tools.GetNow(), remoteAddr)
				AINum := buffer[7]
				AICode := buffer[8]
				ChannelNum := buffer[9]
				fmt.Printf("[%s ~ %s]# DQ总数=%d, DQ序号=%02d, DQ通道数=%d\n", tools.GetNow(), remoteAddr, AINum, AICode, ChannelNum)
				contentBytes := buffer[10 : n-5]
				blockLength := 3
				if len(contentBytes) != int(ChannelNum)*blockLength {
					fmt.Printf("[%s ~ %s]# DQ通道数与实际不匹配\n", tools.GetNow(), remoteAddr)
					continue
				}
				for i := 0; i < int(ChannelNum); i++ {
					shield := contentBytes[i*blockLength]
					shieldTime := tools.BytesToUint16(contentBytes[i*blockLength+1:i*blockLength+3], "big")
					data = append(data, []string{
						fmt.Sprintf("%02d", i),
						fmt.Sprintf("%d", shield),
						fmt.Sprintf("%d", shieldTime),
					})

					/*--- 更新数据规模 start ---*/
					frameItem = append(frameItem, &pkg.FrameItem{
						Code4:       fmt.Sprintf("%03d", i),
						Addr:        fmt.Sprintf("%s-%s-%s-%03d", m.Code1, m.Code2, m.Code3, i),
						Shield:      shield,
						ShieldTime:  int(shieldTime),
						ChannelType: "DQ",
					})
					/*--- 更新数据规模 end ---*/
				}
				/*--- 更新数据规模 start ---*/
				m.FrameItem = frameItem
				pkg.UpdateFSE(fse, m)
				/*--- 更新数据规模 end ---*/

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"通道号", "脉冲选择", "脉冲时间"})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()

				_, err = client.Connection.Write([]byte{0x5a, 0x02, 0x05, 0x00, 0x0F, 0x01, 0x01, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0205")
					continue
				}
			case 0x06:
				/*--- 更新数据规模 start ---*/
				m := &pkg.FSModule{}
				m.Code1 = code1
				m.Code2 = "04"
				m.Code3 = fmt.Sprintf("%02d", buffer[8])
				frameItem := make([]*pkg.FrameItem, 0)
				/*--- 更新数据规模 end ---*/

				fmt.Printf("[%s ~ %s]# Other模块下载\n", tools.GetNow(), remoteAddr)
				AINum := buffer[7]
				AICode := buffer[8]
				ChannelNum := buffer[9]
				fmt.Printf("[%s ~ %s]# Other总数=%d, Other序号=%02d, Other通道数=%d\n", tools.GetNow(), remoteAddr, AINum, AICode, ChannelNum)
				contentBytes := buffer[10 : n-5]

				blockNum := 0
				blockAIAQLength := 28
				blockDIDQLength := 3
				i := 0 // 当前字节位置
				for {
					if i >= len(contentBytes) {
						if blockNum != int(ChannelNum) {
							fmt.Printf("[%s ~ %s]# Other通道数与实际不匹配\n", tools.GetNow(), remoteAddr)
							continue loop0
						}
						break
					}
					channelType := contentBytes[i]
					if channelType == 0x01 || channelType == 0x02 {
						i++
						if i+blockAIAQLength > len(contentBytes) {
							fmt.Printf("[%s ~ %s]# Other字节内容即将超出blockAIAQLength\n", tools.GetNow(), remoteAddr)
							continue loop0
						}
						upperLimitValue := tools.BytesToFloat32(contentBytes[i:i+4], "little")
						i += 4
						lowerLimitValue := tools.BytesToFloat32(contentBytes[i:i+4], "little")
						i += 4
						upper2LimitValue := tools.BytesToFloat32(contentBytes[i:i+4], "little")
						i += 4
						lower2LimitValue := tools.BytesToFloat32(contentBytes[i:i+4], "little")
						i += 4
						rangeUpperValue := tools.BytesToFloat32(contentBytes[i:i+4], "little")
						i += 4
						rangeLowerValue := tools.BytesToFloat32(contentBytes[i:i+4], "little")
						i += 4
						shield := contentBytes[i]
						i++
						alertBit := contentBytes[i]
						i++
						formula := contentBytes[i]
						i++
						diagMode := contentBytes[i]
						i++
						data = append(data, []string{
							fmt.Sprintf("%02d", blockNum),
							fmt.Sprintf("%#02x", channelType),
							fmt.Sprintf("%.2f", upperLimitValue),
							fmt.Sprintf("%.2f", lowerLimitValue),
							fmt.Sprintf("%.2f", upper2LimitValue),
							fmt.Sprintf("%.2f", lower2LimitValue),
							fmt.Sprintf("%.2f", rangeUpperValue),
							fmt.Sprintf("%.2f", rangeLowerValue),
							fmt.Sprintf("%d", shield),
							fmt.Sprintf("%d", alertBit),
							fmt.Sprintf("%d", formula),
							fmt.Sprintf("%d", diagMode),
						})

						blockNum++

						/*--- 更新数据规模 start ---*/
						frameItem = append(frameItem, &pkg.FrameItem{
							Code4:            fmt.Sprintf("%03d", blockNum-1),
							Addr:             fmt.Sprintf("%s-%s-%s-%03d", m.Code1, m.Code2, m.Code3, blockNum-1),
							UpperLimitValue:  float64(upperLimitValue),
							LowerLimitValue:  float64(lowerLimitValue),
							Upper2LimitValue: float64(upper2LimitValue),
							Lower2LimitValue: float64(lower2LimitValue),
							RangeUpperLimit:  float64(rangeUpperValue),
							RangeLowerLimit:  float64(rangeLowerValue),
							Shield:           shield,
							AlertBit:         alertBit,
							Formula:          formula,
							DiagMode:         diagMode,
							ChannelType:      pkg.OtherModuleType(channelType),
						})
						/*--- 更新数据规模 end ---*/
					} else if channelType == 0x03 || channelType == 0x04 {
						i++
						if i+blockDIDQLength > len(contentBytes) {
							fmt.Printf("[%s ~ %s]# Other字节内容即将超出blockDIDQLength\n", tools.GetNow(), remoteAddr)
							continue loop0
						}
						shield := contentBytes[i]
						i++
						shieldTime := tools.BytesToUint16(contentBytes[i:i+2], "big")
						i += 2
						data = append(data, []string{
							fmt.Sprintf("%02d", blockNum),
							fmt.Sprintf("%#02x", channelType),
							fmt.Sprintf("%d", shield),
							fmt.Sprintf("%d", shieldTime),
						})
						blockNum++

						/*--- 更新数据规模 start ---*/
						frameItem = append(frameItem, &pkg.FrameItem{
							Code4:       fmt.Sprintf("%03d", blockNum-1),
							Addr:        fmt.Sprintf("%s-%s-%s-%03d", m.Code1, m.Code2, m.Code3, blockNum-1),
							Shield:      shield,
							ShieldTime:  int(shieldTime),
							ChannelType: pkg.OtherModuleType(channelType),
						})
						/*--- 更新数据规模 end ---*/
					} else {
						fmt.Println("Other模块无效的通道类型", channelType)
						continue loop0
					}

				}

				/*--- 更新数据规模 start ---*/
				m.FrameItem = frameItem
				pkg.UpdateFSE(fse, m)
				/*--- 更新数据规模 end ---*/

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"通道号", "通道类型", "上限", "下限", "上上限", "下下限", "量程上限", "量程下限", "屏蔽", "报警", "计算公式", "诊断模式"})
				table.Append([]string{"通道号", "通道类型", "滤波/脉冲选择", "滤波/持续时间"})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()

				_, err = client.Connection.Write([]byte{0x5a, 0x02, 0x06, 0x00, 0x0F, 0x01, 0x01, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0206")
					continue
				}
			}
		case 0x03:
			switch cmdCode {
			case 0x01:
				/*--- 更新数据规模 start ---*/
				fsm := &pkg.FSModule{}
				fsm.Code1 = code1
				fsm.Code2 = "05"
				fsm.Code3 = fmt.Sprintf("%02d", buffer[6])
				/*--- 更新数据规模 end ---*/

				fmt.Printf("[%s ~ %s]# 泵组电磁阀模块下载\n", tools.GetNow(), remoteAddr)
				modelNum := buffer[5]
				modelCode := buffer[6]
				fmt.Printf("[%s ~ %s]# 模型总数=%d, 模型序号=%02d\n", tools.GetNow(), remoteAddr, modelNum, modelCode)
				m := pkg.BengzuModel{}
				i := 8
				m.BengzuStartControlValue = buffer[i]
				i++
				m.BengzuStopControlValue = buffer[i]
				i++
				m.BengzuStartStateValue = buffer[i]
				i++
				m.BengzuStopStateValue = buffer[i]
				i++
				m.LiansuoValue = buffer[i]
				i++
				m.RemoteLocalValue = buffer[i]
				i++
				m.ControlMethodValue = buffer[i]
				i++
				m.BengzuParam1Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 4
				m.BengzuParam2Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 4
				m.BengzuParam3Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 4
				m.BengzuParam4Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 4
				m.BengzuParam5Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 4
				i++
				m.BengqianPressure = Bytes2Addr(code1, "AI", buffer[i], buffer[i+1])
				i += 2

				m.BengqianStartControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.BengqianStopControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.BengqianStartState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				m.BengqianStopState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2

				m.QianjibengStartControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.QianjibengStopControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.QianjibengStartState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				m.QianjibengStopState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2

				m.LuocibengStartControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.LuocibengStopControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.LuocibengStartState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				m.LuocibengStopState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2

				data = append(data, []string{
					fmt.Sprintf("%s", "开控制"),
					fmt.Sprintf("%d", m.BengzuStartControlValue),
					fmt.Sprintf("%s", "关控制"),
					fmt.Sprintf("%d", m.BengzuStopControlValue),
					fmt.Sprintf("%s", "开状态"),
					fmt.Sprintf("%d", m.BengzuStartStateValue),
					fmt.Sprintf("%s", "关状态"),
					fmt.Sprintf("%d", m.BengzuStopStateValue),
				})
				data = append(data, []string{
					fmt.Sprintf("%s", "连锁"),
					fmt.Sprintf("%d", m.LiansuoValue),
					fmt.Sprintf("%s", "远程就地"),
					fmt.Sprintf("%d", m.RemoteLocalValue),
					fmt.Sprintf("%s", "控制方法"),
					fmt.Sprintf("%d", m.ControlMethodValue),
					fmt.Sprintf("%s", "参数一"),
					fmt.Sprintf("%.2f", m.BengzuParam1Value),
				})
				data = append(data, []string{
					fmt.Sprintf("%s", "参数2"),
					fmt.Sprintf("%.2f", m.BengzuParam2Value),
					fmt.Sprintf("%s", "参数3"),
					fmt.Sprintf("%.2f", m.BengzuParam3Value),
					fmt.Sprintf("%s", "参数4"),
					fmt.Sprintf("%.2f", m.BengzuParam4Value),
					fmt.Sprintf("%s", "参数5"),
					fmt.Sprintf("%.2f", m.BengzuParam5Value),
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "泵前-启动控制"),
					fmt.Sprintf("%s", m.BengqianStartControl),
					fmt.Sprintf("%s", "泵前-停止控制"),
					fmt.Sprintf("%s", m.BengqianStopControl),
					fmt.Sprintf("%s", "泵前-启动状态"),
					fmt.Sprintf("%s", m.BengqianStartState),
					fmt.Sprintf("%s", "泵前-停止状态"),
					fmt.Sprintf("%s", m.BengqianStopState),
				})
				data = append(data, []string{
					fmt.Sprintf("%s", "罗茨泵-启动控制"),
					fmt.Sprintf("%s", m.QianjibengStartControl),
					fmt.Sprintf("%s", "罗茨泵-停止控制"),
					fmt.Sprintf("%s", m.QianjibengStopControl),
					fmt.Sprintf("%s", "罗茨泵-启动状态"),
					fmt.Sprintf("%s", m.QianjibengStartState),
					fmt.Sprintf("%s", "罗茨泵-停止状态"),
					fmt.Sprintf("%s", m.QianjibengStopState),
				})
				data = append(data, []string{
					fmt.Sprintf("%s", "前级泵-启动控制"),
					fmt.Sprintf("%s", m.LuocibengStartControl),
					fmt.Sprintf("%s", "前级泵-停止控制"),
					fmt.Sprintf("%s", m.LuocibengStopControl),
					fmt.Sprintf("%s", "前级泵-启动状态"),
					fmt.Sprintf("%s", m.LuocibengStartState),
					fmt.Sprintf("%s", "前级泵-停止状态"),
					fmt.Sprintf("%s", m.LuocibengStopState),
				})
				data = append(data, []string{
					fmt.Sprintf("%s", "泵前压力"),
					fmt.Sprintf("%s", m.BengqianPressure),
					"", "", "", "", "", "",
				})

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"", "", "", "", "", "", "", ""})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()

				/*--- 更新数据规模 start ---*/
				fsm.BengzuModel = &m
				pkg.UpdateFSE(fse, fsm)
				/*--- 更新数据规模 end ---*/
				_, err = client.Connection.Write([]byte{0x5a, 0x03, 0x01, 0x00, 0x0C, modelNum, modelCode, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0301")
					continue
				}
			case 0x02:
				/*--- 更新数据规模 start ---*/
				fsm := &pkg.FSModule{}
				fsm.Code1 = code1
				fsm.Code2 = "06"
				fsm.Code3 = fmt.Sprintf("%02d", buffer[6])
				/*--- 更新数据规模 end ---*/

				fmt.Printf("[%s ~ %s]# 增压泵电磁阀模块下载\n", tools.GetNow(), remoteAddr)
				modelNum := buffer[5]
				modelCode := buffer[6]
				fmt.Printf("[%s ~ %s]# 模型总数=%d, 模型序号=%02d\n", tools.GetNow(), remoteAddr, modelNum, modelCode)
				m := pkg.ZengyaModel{}
				i := 8
				m.LiansuoValue = buffer[i]
				i++
				m.RemoteLocalValue = buffer[i]
				i++
				m.ControlMethodValue = buffer[i]
				i += 2

				m.BengqianPressure = Bytes2Addr(code1, "AI", buffer[i], buffer[i+1])
				i += 2

				m.BengqianStartControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.BengqianStopControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.BengqianStartState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				m.BengqianStopState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2

				m.ZengyaStartControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.ZengyaStopControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.ZengyaStartState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				m.ZengyaStopState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2

				data = append(data, []string{
					fmt.Sprintf("%s", "连锁"),
					fmt.Sprintf("%d", m.LiansuoValue),
					fmt.Sprintf("%s", "远程就地"),
					fmt.Sprintf("%d", m.RemoteLocalValue),
					fmt.Sprintf("%s", "控制方法"),
					fmt.Sprintf("%d", m.ControlMethodValue),
					fmt.Sprintf("%s", "泵前压力"),
					fmt.Sprintf("%s", m.BengqianPressure),
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "泵前-启动控制"),
					fmt.Sprintf("%s", m.BengqianStartControl),
					fmt.Sprintf("%s", "泵前-停止控制"),
					fmt.Sprintf("%s", m.BengqianStopControl),
					fmt.Sprintf("%s", "泵前-启动状态"),
					fmt.Sprintf("%s", m.BengqianStartState),
					fmt.Sprintf("%s", "泵前-停止状态"),
					fmt.Sprintf("%s", m.BengqianStopState),
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "增压泵-启动控制"),
					fmt.Sprintf("%s", m.ZengyaStartControl),
					fmt.Sprintf("%s", "增压泵-停止控制"),
					fmt.Sprintf("%s", m.ZengyaStopControl),
					fmt.Sprintf("%s", "增压泵-启动状态"),
					fmt.Sprintf("%s", m.ZengyaStartState),
					fmt.Sprintf("%s", "增压泵-停止状态"),
					fmt.Sprintf("%s", m.ZengyaStopState),
				})

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"", "", "", "", "", "", "", ""})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()
				/*--- 更新数据规模 start ---*/
				fsm.ZengyaModel = &m
				pkg.UpdateFSE(fse, fsm)
				/*--- 更新数据规模 end ---*/
				_, err = client.Connection.Write([]byte{0x5a, 0x03, 0x02, 0x00, 0x0C, modelNum, modelCode, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0302")
					continue
				}
			case 0x03:
				/*--- 更新数据规模 start ---*/
				fsm := &pkg.FSModule{}
				fsm.Code1 = code1
				fsm.Code2 = "07"
				fsm.Code3 = fmt.Sprintf("%02d", buffer[6])
				/*--- 更新数据规模 end ---*/
				fmt.Printf("[%s ~ %s]# 电调阀模块下载\n", tools.GetNow(), remoteAddr)
				modelNum := buffer[5]
				modelCode := buffer[6]
				fmt.Printf("[%s ~ %s]# 模型总数=%d, 模型序号=%02d\n", tools.GetNow(), remoteAddr, modelNum, modelCode)
				m := pkg.DiantiaoSVModel{}
				i := 8
				m.CurrentKaidu = Bytes2Addr(code1, "AI", buffer[i], buffer[i+1])
				i += 2
				m.SetKaidu = Bytes2Addr(code1, "AQ", buffer[i], buffer[i+1])
				i += 2
				m.Control = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.SetStep = Bytes2Addr(code1, "AQ", buffer[i], buffer[i+1])
				i += 2
				m.SelfInspection = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.Up = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.Down = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.AllOn = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.AllOff = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2

				m.AllOnState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				m.AllOffState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				m.QianjiPressure = Bytes2Addr(code1, "AI", buffer[i], buffer[i+1])
				i += 2
				m.HoujiPressure = Bytes2Addr(code1, "AI", buffer[i], buffer[i+1])
				i += 2
				m.DestPressure = Bytes2Addr(code1, "AQ", buffer[i], buffer[i+1])
				i += 2
				m.P = Bytes2Addr(code1, "AQ", buffer[i], buffer[i+1])
				i += 2
				m.I = Bytes2Addr(code1, "AQ", buffer[i], buffer[i+1])
				i += 2
				m.D = Bytes2Addr(code1, "AQ", buffer[i], buffer[i+1])
				i += 2
				m.CustomStartControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.CustomStopControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.CustomStartState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				m.CustomStopState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				m.PID = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.RemoteLocal = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.ControlMethod = Bytes2Addr(code1, "AQ", buffer[i], buffer[i+1])
				i += 2

				data = append(data, []string{
					fmt.Sprintf("%s", "当前开度"),
					fmt.Sprintf("%s", m.CurrentKaidu),
					fmt.Sprintf("%s", "设置开度"),
					fmt.Sprintf("%s", m.SetKaidu),
					fmt.Sprintf("%s", "控制"),
					fmt.Sprintf("%s", m.Control),
					fmt.Sprintf("%s", "设置步长"),
					fmt.Sprintf("%s", m.SetStep),
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "自检控制"),
					fmt.Sprintf("%s", m.SelfInspection),
					fmt.Sprintf("%s", "上调"),
					fmt.Sprintf("%s", m.Up),
					fmt.Sprintf("%s", "下调"),
					fmt.Sprintf("%s", m.Down),
					fmt.Sprintf("%s", "全开"),
					fmt.Sprintf("%s", m.AllOn),
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "全关"),
					fmt.Sprintf("%s", m.AllOff),
					fmt.Sprintf("%s", "全开状态"),
					fmt.Sprintf("%s", m.AllOnState),
					fmt.Sprintf("%s", "全关状态"),
					fmt.Sprintf("%s", m.AllOffState),
					fmt.Sprintf("%s", "前级压力"),
					fmt.Sprintf("%s", m.QianjiPressure),
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "后级压力"),
					fmt.Sprintf("%s", m.HoujiPressure),
					fmt.Sprintf("%s", "目标压力"),
					fmt.Sprintf("%s", m.DestPressure),
					fmt.Sprintf("%s", "P"),
					fmt.Sprintf("%s", m.P),
					fmt.Sprintf("%s", "I"),
					fmt.Sprintf("%s", m.I),
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "D"),
					fmt.Sprintf("%s", m.D),
					fmt.Sprintf("%s", "自整定-启动控制"),
					fmt.Sprintf("%s", m.CustomStartControl),
					fmt.Sprintf("%s", "自整定-停止控制"),
					fmt.Sprintf("%s", m.CustomStopControl),
					fmt.Sprintf("%s", "自整定-启动状态"),
					fmt.Sprintf("%s", m.CustomStartState),
				})
				data = append(data, []string{
					fmt.Sprintf("%s", "自整定-停止状态"),
					fmt.Sprintf("%s", m.CustomStopState),
					fmt.Sprintf("%s", "PID"),
					fmt.Sprintf("%s", m.PID),
					fmt.Sprintf("%s", "远程就地"),
					fmt.Sprintf("%s", m.RemoteLocal),
					fmt.Sprintf("%s", "控制方法"),
					fmt.Sprintf("%s", m.ControlMethod),
				})

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"", "", "", "", "", "", "", ""})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()
				/*--- 更新数据规模 start ---*/
				fsm.DiantiaoSVModel = &m
				pkg.UpdateFSE(fse, fsm)
				/*--- 更新数据规模 end ---*/
				_, err = client.Connection.Write([]byte{0x5a, 0x03, 0x03, 0x00, 0x0C, modelNum, modelCode, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0303")
					continue
				}
			case 0x04:
				/*--- 更新数据规模 start ---*/
				fsm := &pkg.FSModule{}
				fsm.Code1 = code1
				fsm.Code2 = "08"
				fsm.Code3 = fmt.Sprintf("%02d", buffer[6])
				/*--- 更新数据规模 end ---*/
				fmt.Printf("[%s ~ %s]# 压力电磁阀模块下载\n", tools.GetNow(), remoteAddr)
				modelNum := buffer[5]
				modelCode := buffer[6]
				fmt.Printf("[%s ~ %s]# 模型总数=%d, 模型序号=%02d\n", tools.GetNow(), remoteAddr, modelNum, modelCode)
				m := pkg.PressureSVModel{}
				i := 8
				m.LiansuoValue = buffer[i]
				i++
				m.ControlMethodValue = buffer[i]
				i += 2
				m.Pressure = Bytes2Addr(code1, "AI", buffer[i], buffer[i+1])
				i += 2

				m.SVStartControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.SVStopControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.SVStartState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				m.SVStopState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				data = append(data, []string{
					fmt.Sprintf("%s", "连锁"),
					fmt.Sprintf("%d", m.LiansuoValue),
					fmt.Sprintf("%s", "控制方法"),
					fmt.Sprintf("%d", m.ControlMethodValue),
					fmt.Sprintf("%s", "压力"),
					fmt.Sprintf("%s", m.Pressure),
					"", "",
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "电磁阀-启动控制"),
					fmt.Sprintf("%s", m.SVStartControl),
					fmt.Sprintf("%s", "电磁阀-停止控制"),
					fmt.Sprintf("%s", m.SVStopControl),
					fmt.Sprintf("%s", "电磁阀-启动状态"),
					fmt.Sprintf("%s", m.SVStartState),
					fmt.Sprintf("%s", "电磁阀-停止状态"),
					fmt.Sprintf("%s", m.SVStopState),
				})
				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"", "", "", "", "", "", "", ""})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()
				/*--- 更新数据规模 start ---*/
				fsm.PressureSVModel = &m
				pkg.UpdateFSE(fse, fsm)
				/*--- 更新数据规模 end ---*/
				_, err = client.Connection.Write([]byte{0x5a, 0x03, 0x04, 0x00, 0x0C, modelNum, modelCode, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0304")
					continue
				}
			case 0x05:
				/*--- 更新数据规模 start ---*/
				fsm := &pkg.FSModule{}
				fsm.Code1 = code1
				fsm.Code2 = "09"
				fsm.Code3 = fmt.Sprintf("%02d", buffer[6])
				/*--- 更新数据规模 end ---*/
				fmt.Printf("[%s ~ %s]# 电源控制模块下载\n", tools.GetNow(), remoteAddr)
				modelNum := buffer[5]
				modelCode := buffer[6]
				fmt.Printf("[%s ~ %s]# 模型总数=%d, 模型序号=%02d\n", tools.GetNow(), remoteAddr, modelNum, modelCode)
				m := pkg.PowerModel{}
				i := 9
				m.U1Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 5
				m.U2Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 5
				m.U3Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 5
				m.I1Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 5
				m.I2Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 5
				m.I3Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 5
				m.FValue = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 5
				m.ActivePowerValue = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 5
				m.ReactivePowerValue = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 5
				m.ApparentPowerValue = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				data = append(data, []string{
					fmt.Sprintf("%s", "U1"),
					fmt.Sprintf("%.2f", m.U1Value),
					fmt.Sprintf("%s", "U2"),
					fmt.Sprintf("%.2f", m.U2Value),
					fmt.Sprintf("%s", "U3"),
					fmt.Sprintf("%.2f", m.U3Value),
					fmt.Sprintf("%s", "I1"),
					fmt.Sprintf("%.2f", m.I1Value),
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "I2"),
					fmt.Sprintf("%.2f", m.I2Value),
					fmt.Sprintf("%s", "I3"),
					fmt.Sprintf("%.2f", m.I3Value),
					fmt.Sprintf("%s", "F"),
					fmt.Sprintf("%.2f", m.FValue),
					fmt.Sprintf("%s", "有功功率"),
					fmt.Sprintf("%.2f", m.ActivePowerValue),
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "无功功率"),
					fmt.Sprintf("%.2f", m.ReactivePowerValue),
					fmt.Sprintf("%s", "视在功率"),
					fmt.Sprintf("%.2f", m.ApparentPowerValue),
					"", "", "", "",
				})

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"", "", "", "", "", "", "", ""})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()
				/*--- 更新数据规模 start ---*/
				fsm.PowerModel = &m
				pkg.UpdateFSE(fse, fsm)
				/*--- 更新数据规模 end ---*/
				_, err = client.Connection.Write([]byte{0x5a, 0x03, 0x05, 0x00, 0x0C, modelNum, modelCode, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0305")
					continue
				}
			case 0x06:
				/*--- 更新数据规模 start ---*/
				fsm := &pkg.FSModule{}
				fsm.Code1 = code1
				fsm.Code2 = "10"
				fsm.Code3 = fmt.Sprintf("%02d", buffer[6])
				/*--- 更新数据规模 end ---*/
				fmt.Printf("[%s ~ %s]# 电源状态模块下载\n", tools.GetNow(), remoteAddr)
				modelNum := buffer[5]
				modelCode := buffer[6]
				fmt.Printf("[%s ~ %s]# 模型总数=%d, 模型序号=%02d\n", tools.GetNow(), remoteAddr, modelNum, modelCode)
				m := pkg.PowerStateModel{}
				i := 9
				m.RunningStateValue = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 5
				m.ErrorStateValue = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				data = append(data, []string{
					fmt.Sprintf("%s", "运行状态"),
					fmt.Sprintf("%.2f", m.RunningStateValue),
					fmt.Sprintf("%s", "故障状态"),
					fmt.Sprintf("%.2f", m.ErrorStateValue),
					"", "", "", "",
				})

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"", "", "", "", "", "", "", ""})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()
				/*--- 更新数据规模 start ---*/
				fsm.PowerStateModel = &m
				pkg.UpdateFSE(fse, fsm)
				/*--- 更新数据规模 end ---*/
				_, err = client.Connection.Write([]byte{0x5a, 0x03, 0x06, 0x00, 0x0C, modelNum, modelCode, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0306")
					continue
				}
			case 0x07:
				/*--- 更新数据规模 start ---*/
				fsm := &pkg.FSModule{}
				fsm.Code1 = code1
				fsm.Code2 = "13"
				fsm.Code3 = fmt.Sprintf("%02d", buffer[6])
				/*--- 更新数据规模 end ---*/
				fmt.Printf("[%s ~ %s]# 模态采集模块下载\n", tools.GetNow(), remoteAddr)
				modelNum := buffer[5]
				modelCode := buffer[6]
				fmt.Printf("[%s ~ %s]# 模型总数=%d, 模型序号=%02d\n", tools.GetNow(), remoteAddr, modelNum, modelCode)
				m := pkg.ModeCollectModel{}
				i := 8
				m.StimulatePoint = Bytes2Addr(code1, "AI", buffer[i], buffer[i+1])
				i += 2
				m.ResponsePoint = Bytes2Addr(code1, "AI", buffer[i], buffer[i+1])
				i += 2
				m.StartControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.StopControl = Bytes2Addr(code1, "DQ", buffer[i], buffer[i+1])
				i += 2
				m.StartState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])
				i += 2
				m.StopState = Bytes2Addr(code1, "DI", buffer[i], buffer[i+1])

				data = append(data, []string{
					fmt.Sprintf("%s", "激励点位"),
					fmt.Sprintf("%s", m.StimulatePoint),
					fmt.Sprintf("%s", "响应点位"),
					fmt.Sprintf("%s", m.ResponsePoint),
					fmt.Sprintf("%s", "开控制"),
					fmt.Sprintf("%s", m.StartControl),
					fmt.Sprintf("%s", "关控制"),
					fmt.Sprintf("%s", m.StopControl),
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "开状态"),
					fmt.Sprintf("%s", m.StartState),
					fmt.Sprintf("%s", "关状态"),
					fmt.Sprintf("%s", m.StopState),
					"", "", "", "",
				})

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"", "", "", "", "", "", "", ""})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()
				/*--- 更新数据规模 start ---*/
				fsm.ModeCollectModel = &m
				pkg.UpdateFSE(fse, fsm)
				/*--- 更新数据规模 end ---*/
				_, err = client.Connection.Write([]byte{0x5a, 0x03, 0x07, 0x00, 0x0C, modelNum, modelCode, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0307")
					continue
				}
			case 0x08:
				/*--- 更新数据规模 start ---*/
				fsm := &pkg.FSModule{}
				fsm.Code1 = code1
				fsm.Code2 = "14"
				fsm.Code3 = fmt.Sprintf("%02d", buffer[6])
				/*--- 更新数据规模 end ---*/
				fmt.Printf("[%s ~ %s]# 故障诊断模块下载\n", tools.GetNow(), remoteAddr)
				modelNum := buffer[5]
				modelCode := buffer[6]
				fmt.Printf("[%s ~ %s]# 模型总数=%d, 模型序号=%02d\n", tools.GetNow(), remoteAddr, modelNum, modelCode)
				m := pkg.DiagModel{}
				i := 8
				m.DiagModeValue = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 4
				m.DiagParam1Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 4
				m.DiagParam2Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 4
				m.DiagParam3Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 4
				m.DiagParam4Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				i += 4
				m.DiagParam5Value = float64(tools.BytesToFloat32(buffer[i:i+4], "little"))
				data = append(data, []string{
					fmt.Sprintf("%s", "诊断模式"),
					fmt.Sprintf("%.2f", m.DiagModeValue),
					fmt.Sprintf("%s", "诊断参数1"),
					fmt.Sprintf("%.2f", m.DiagParam1Value),
					fmt.Sprintf("%s", "诊断参数2"),
					fmt.Sprintf("%.2f", m.DiagParam2Value),
					fmt.Sprintf("%s", "诊断参数3"),
					fmt.Sprintf("%.2f", m.DiagParam3Value),
				})

				data = append(data, []string{
					fmt.Sprintf("%s", "诊断参数4"),
					fmt.Sprintf("%.2f", m.DiagParam4Value),
					fmt.Sprintf("%s", "诊断参数5"),
					fmt.Sprintf("%.2f", m.DiagParam5Value),
					"", "", "", "",
				})

				table := tablewriter.NewWriter(os.Stdout)
				table.SetHeader([]string{"", "", "", "", "", "", "", ""})
				for _, v := range data {
					table.Append(v)
				}
				table.Render()
				/*--- 更新数据规模 start ---*/
				fsm.DiagModel = &m
				pkg.UpdateFSE(fse, fsm)
				/*--- 更新数据规模 end ---*/
				_, err = client.Connection.Write([]byte{0x5a, 0x03, 0x08, 0x00, 0x0C, modelNum, modelCode, 0x00, 0x00, 0x00, 0x00, 0xa5})
				if err != nil {
					fmt.Println("TCP 写入失败 0308")
					continue
				}
			}
		case 0x04:
			switch cmdCode {
			case 0x01:
				// FS基本信息读取返回
				respData := pkg.GenFSFrameData0401(fse.DS)
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0401")
					continue
				}
			default:
				// 5大模块上载响应
				respData, err := pkg.GenFSFrameData04(fse, cmdCode, buffer[8])
				if err != nil {
					fmt.Println(err.Error())
					continue
				}
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0402")
					continue
				}
			}
		case 0x05:
			switch cmdCode {
			case 0x01:
				// 模型配置基本信息读取返回
				respData := pkg.GenFSFrameData0501(fse.DS)
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0501")
					continue
				}
			case 0x02:
				modelNumber := buffer[6]
				respData, err := pkg.GenFSModuleData0502(fse, fmt.Sprintf("%02d", modelNumber))
				if err != nil {
					fmt.Println("模型上载返回错误:", err.Error())
					continue
				}
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0502")
					continue
				}
			case 0x03:
				modelNumber := buffer[6]
				respData, err := pkg.GenFSModuleData0503(fse, fmt.Sprintf("%02d", modelNumber))
				if err != nil {
					fmt.Println("模型上载返回错误:", err.Error())
					continue
				}
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0503")
					continue
				}
			case 0x04:
				modelNumber := buffer[6]
				respData, err := pkg.GenFSModuleData0504(fse, fmt.Sprintf("%02d", modelNumber))
				if err != nil {
					fmt.Println("模型上载返回错误:", err.Error())
					continue
				}
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0504")
					continue
				}
			case 0x05:
				modelNumber := buffer[6]
				respData, err := pkg.GenFSModuleData0505(fse, fmt.Sprintf("%02d", modelNumber))
				if err != nil {
					fmt.Println("模型上载返回错误:", err.Error())
					continue
				}
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0505")
					continue
				}
			case 0x06:
				modelNumber := buffer[6]
				respData, err := pkg.GenFSModuleData0506(fse, fmt.Sprintf("%02d", modelNumber))
				if err != nil {
					fmt.Println("模型上载返回错误:", err.Error())
					continue
				}
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0506")
					continue
				}
			case 0x07:
				modelNumber := buffer[6]
				respData, err := pkg.GenFSModuleData0507(fse, fmt.Sprintf("%02d", modelNumber))
				if err != nil {
					fmt.Println("模型上载返回错误:", err.Error())
					continue
				}
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0507")
					continue
				}
			case 0x08:
				modelNumber := buffer[6]
				respData, err := pkg.GenFSModuleData0508(fse, fmt.Sprintf("%02d", modelNumber))
				if err != nil {
					fmt.Println("模型上载返回错误:", err.Error())
					continue
				}
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0508")
					continue
				}
			case 0x09:
				modelNumber := buffer[6]
				respData, err := pkg.GenFSModuleData0509(fse, fmt.Sprintf("%02d", modelNumber))
				if err != nil {
					fmt.Println("模型上载返回错误:", err.Error())
					continue
				}
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0509")
					continue
				}
			}
		case 0x06:
			switch cmdCode {
			case 0x01:
				respData := pkg.GenFSFrameData0601(fse.DS)
				_, err = client.Connection.Write(respData)
				if err != nil {
					fmt.Println("TCP 写入失败 0601")
					continue
				}
			case 0x02:
				err = pkg.Response0602(fse, client)
				if err != nil {
					fmt.Println("Response0602 失败", err.Error())
					continue loop0
				}
			case 0x03:
				fmt.Printf("[%s ~ %s]# cmd=%02d%02d\n", tools.GetNow(), remoteAddr, funcCode, cmdCode)
				err = pkg.Response0603(fse, client)
				if err != nil {
					fmt.Println("Response0603 失败", err.Error())
					continue loop0
				}
			case 0x04:
				fmt.Printf("[%s ~ %s]# cmd=%02d%02d\n", tools.GetNow(), remoteAddr, funcCode, cmdCode)
				err = pkg.ReceiveHandle0604(fse, buffer[0:n])
				if err != nil {
					fmt.Println("ReceiveHandle0604 失败", err.Error())
					err = pkg.Response0684(fse, client)
					if err != nil {
						fmt.Println("Response0684 失败", err.Error())
					}
					continue loop0
				}
				/*--- 修改AI成功后返回运行同步数据 ---*/
				err = pkg.Response0604(fse, client)
				if err != nil {
					fmt.Println("Response0603 失败", err.Error())
					continue loop0
				}
			default:
				fmt.Printf("[%s ~ %s]# 暂不支持的功能码 %02d%02d\n", tools.GetNow(), remoteAddr, funcCode, cmdCode)
			}
		default:
			fmt.Printf("[%s ~ %s]# 暂不支持的功能码\n", tools.GetNow(), remoteAddr)
		}

		/* --- 处理 rawData 结束 --- */
		clearBuffer(&buffer, n)

	}
}

// 连接管理, 检查连接是否在线, 删除离线的client
func connManage() {
	// 连接和断开管理
	go func() {
		for {
			select {
			case client := <-OnlineMap.Register:
				OnlineMap.RLock()
				_, ok := OnlineMap.M[client.RemoteAddr]
				OnlineMap.RUnlock()
				if !ok {
					fmt.Printf("[%s ~ %s]# 新客户端已连接\n", tools.GetNow(), client.RemoteAddr)
				}
				client.LastDataTime = time.Now()
				OnlineMap.Lock()
				OnlineMap.M[client.RemoteAddr] = client
				OnlineMap.Unlock()
			case client := <-OnlineMap.Unregister:
				fmt.Printf("用户掉线 %s\n", client.RemoteAddr)
				_ = client.Connection.Close()
				OnlineMap.Lock()
				delete(OnlineMap.M, client.RemoteAddr)
				OnlineMap.Unlock()
			}
		}
	}()

}

func WriteAll(data []byte) {
	OnlineMap.RLock()
	defer OnlineMap.RUnlock()
	for _, client := range OnlineMap.M {
		_, err := client.Connection.Write(data)
		if err != nil {
			fmt.Println("TCP写入失败 WriteAll")
			continue
		}
	}
}

// 重置rawData
func resetRawData(rawData []byte, toIndex int) []byte {
	if len(rawData) > toIndex {
		rawData = rawData[toIndex:]
	} else {
		rawData = make([]byte, 0)
	}
	return rawData
}

func clearBuffer(buf *[ByteLENGTH]byte, n int) {
	if n >= ByteLENGTH {
		n = ByteLENGTH
	}
	for i := 0; i < n; i++ {
		buf[i] = 0
	}
}

func Bytes2Addr(code1, modelType string, modelNum, channelNum byte) (addr string) {
	if code1 != "" {
		code1 = code1 + "-"
	}
	code2 := ""
	code3 := fmt.Sprintf("%02d", modelNum)
	code4 := fmt.Sprintf("%02d", channelNum)
	switch modelType {
	case "AI":
		code2 = "00"
	case "AQ":
		code2 = "01"
	case "DI":
		code2 = "02"
	case "DQ":
		code2 = "03"
	case "Other":
		code2 = "04"
	}
	return code1 + code2 + "-" + code3 + "-" + code4
}

/* --- 启动http服务 ---*/

var HttpPort string

func HttpRun() {
	var r *gin.Engine
	gin.SetMode(gin.ReleaseMode)
	r = gin.New()
	r.GET("/", func(ctx *gin.Context) {
		ctx.String(200, "API列表:\n"+
			//"GET /module_upload FS模块上载\n\t--module_type 模块类型\n\t--total 模块总数\n\t--num 序号\n\t--channel_total 通道总数\n"+
			"GET /fse_info 获取设备信息\n"+
			"")
	})
	r.GET("/module_upload", func(ctx *gin.Context) {
		moduleType := ctx.Query("module_type")      // 模块类型
		totalS := ctx.Query("total")                // 模块总数
		numS := ctx.Query("num")                    // 序号
		channelTotalS := ctx.Query("channel_total") // 通道总数
		totalInt, _ := strconv.Atoi(totalS)
		numInt, _ := strconv.Atoi(numS)
		channelTotalInt, _ := strconv.Atoi(channelTotalS)
		total := byte(totalInt)
		num := byte(numInt)
		channelTotal := byte(channelTotalInt)
		if total == 0 {
			ctx.JSON(200, gin.H{
				"code":    2,
				"message": "模型总数不能为0",
				"data":    "",
			})
			return
		}
		data := []byte{0x5a}
		switch moduleType {
		case "AI":
			data = append(data, 0x04, 0x02)
		case "AQ":
			data = append(data, 0x04, 0x03)
		case "DI":
			data = append(data, 0x04, 0x04)
		case "DQ":
			data = append(data, 0x04, 0x05)
		case "Other":
			data = append(data, 0x04, 0x06)
		default:
			ctx.JSON(200, gin.H{
				"code":    2,
				"message": "无效的参数",
				"data":    "",
			})
			return
		}
		data = append(data, 0xff, 0xff, 0x01, 0x01)
		data = append(data, total, num, channelTotal)
		data = append(data, 0x00, 0x00, 0x00, 0x00, 0xa5)

		pkg.FixDataLength(data)

		WriteAll(data)
		ctx.JSON(200, gin.H{
			"code":    0,
			"message": "success",
			"data": map[string]interface{}{
				"hex": tools.ByteArrayToHexStr(data),
			},
		})
	})

	r.GET("/fse_info", func(ctx *gin.Context) {
		ctx.JSON(200, gin.H{
			"code":    0,
			"message": "success",
			"data": map[string]interface{}{
				"info": fse,
			},
		})
	})

	fmt.Printf("%-32s%-32s\n", "http listen on "+HttpPort, "OK")
	err := r.Run(":" + HttpPort)
	if err != nil {
		log.Fatal(err.Error())
	}
}
